home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
World of Education
/
World of Education.iso
/
world_d
/
drfinfo.zip
/
CMOS11.ZIP
/
CMOS.ASM
< prev
next >
Wrap
Assembly Source File
|
1991-09-18
|
18KB
|
724 lines
NAME CMOSSAVE
TITLE CMOSSave Save CMOS to a file on disk or floppy
Comment |
Version 1.1 1991 Sept 07 Roedy Green
works with MASM 6.0 and Optasm
See CMOS.TXT for details on use.
USAGE:
Examples:
*********
CMOSSave A:\MyCMOS.Sav
CMOSRest A:\MyCMOS.Sav
CMOSChk A:\ByCMOS.Sav
Syntax errors or missing file trouble generates an ERRORLEVEL 4.
CMOSChk generates an ERRORLEVEL 1 if the CMOS has changed since
the CMOSSave was done.
Version History
***************
Version 1.0
- released to BIX 91/09/07
Version 1.1
- released to BIX 91/09/18
- added special check for small 64 character CMOSes.
Version 1.2
- not yet written
- add CMOSStuff, like CMOSRest, but computes a valid checksum for you
it might even have a hex edit and a line of description for each byte.
CMOS Usage
**********
2) CMOS RAM map, PC/AT:
offset contents
00h Seconds
01h Second Alarm
02h Minutes
03h Minute Alarm
04h Hours
05h Hour Alarm
06h Day of the Week
07h Day of the Month
08h Month
09h Year
0Ah Status Register A
0Bh Status Register B
0Ch Status Register C
0Dh Status Register D
0Eh Diagnostic Status Byte
0Fh Shutdown Status Byte
10h Disk Drive Type for Drives A: and B:
The drive-type bytes use bits 0:3 for the first
drive and 4:7 for the other
Disk drive types:
00h no drive present
01h double sided 360k
02h high capacity (1.2 meg)
03h-0Fh reserved
11h (AT):Reserved (PS/2):drive type for hard disk C:
12h (PS/2):drive type for hard disk D:
(AT, XT/286):hard disk type for drives C: and D:
Format of drive-type entry for AT, XT/286:
0 number of cyls in drive (0-1023 allowed)
2 number of heads per drive (0-15 allowed)
3 starting reduced write compensation (not
used on AT)
5 starting cylinder for write compensation
7 max. ECC data burst length, XT only
8 control byte
Bit
7 disable disk-access retries
6 disable ECC retries
5-4 reserved, set to zero
3 more than 8 heads
2-0 drive option on XT (not used by AT)
9 timeout value for XT (not used by AT)
12 landing zone cylinder number
14 number of sectors per track (default 17,
0-17 allowed)
13h Reserved
14h Equipment Byte (corresponds to sw. 1 on PC and XT)
15h-16h Base Memory Size (low,high)
17h-18h Expansion Memory Size (low,high)
19h-20h Reserved
(PS/2) POS information Model 50 (60 and 80 use a 2k
CMOS RAM that is not accessible through software)
21h-2Dh Reserved (not checksumed)
2Eh-2Fh Checksum of Bytes 10 Through 20 (low,high)
30h-31h Exp. Memory Size as Det. by POST (low,high)
32h Date Century Byte
33h Information Flags (set during power-on)
34h-3Fh Reserved
3) The alarm function is used to drive the BIOS WAIT function
(int 15h function 90h).
4) To access the configuration RAM write the byte address (00-3Fh)
you need to access to I/O port 70h, then access the data via
I/O port 71h.
5) CMOS RAM chip is a Motorola 146818
6) The equipment byte is used to determine the configuration for
the POST power-on diagnostics.
7) Bytes 00-0Dh are defined by the chip for timing functions,
bytes 0Eh-3Fh are defined by IBM.
8) Compaq 386 uses came CMOS chip as IBM AT. Extra functions:
byte 45 (2Dh) store additional info not maintained by AT
bit 0 indicates is Compaq dual-mode monitor isntalled
1 indicates whether keyclick is enabled
2 not used
3 if non-Compaq graphics adapter installed
Some CMOSes, (SXs) appear to store duplicates of registers 0..3F
in 40..7F, others (DXs) store some other advanced configuration
information in these registers. Thus there are 64 byte and 128
byte CMOSes. We tell them apart by looking for a match in bytes
in the checksum range.
Offsets 10..2F are included in the checksum. We do not ever
need to compute a checksum since we just save and restore.
Register Conventions
********************
Subroutines may trash all registers except those explicity
documented as input or output.
| ; end of comment
; E Q U A T E S
CMOSSAVE EQU 1
CMOSREST EQU 2
CMOSCHK EQU 3
; use /DGenerating#CMOSSAVE
; /DGenerating#CMOSREST
; /DGenerating#CMOSCHK
; on the assembler command line to select which version
; of the code to assemble.
; Or add code following of the form:
GENERATING EQU CMOSSAVE
If Generating eq CMOSSave
%OUT Generating CMOSSave.Com
Endif
If Generating eq CMOSRest
%OUT Generating CMOSRest.Com
endif
If Generating eq CMOSChk
%OUT Generating CMOSChk.Com
endif
;==============================================================
stack segment stack ; keep MS link happy by providing null stack
stack ends
CODE SEGMENT PARA ; start off in code.
;==============================================================
data segment byte ; provide a separate DATA segment
; actually all come after the code
;==============================================================
; V A R I A B L E S
If Generating eq CMOSSave
BannerMsg DB '░▒▓█ CMOSSave 1.1 █▓▒░',13d,10d
DB 13d,10d
DB 'Saves contents of CMOS to a file on hard disk or floppy.',13,10
DB 'Copyright (c) 1991 Roedy Green Canadian Mind Products',13,10
DB 'May be freely distributed and used for any purpose except military.',13,10
DB 13,10
db '$'
UsageMsg DB '░▒▓█ Error █▓▒░',7,13,10
DB 'Insert a formatted diskette.',13,10
DB 'then try:',13,10
DB 'CMOSSav A:MyCMOS.Sav',13,10
DB 'or if wan to save on hard disk try:',13,10
DB 'CMOSSav C:\MyCMOS.Sav',13,10
DB 'Read CMOS.TXT to find how to use it properly.',13,10
db '$'
FileTroubleMsg DB '░▒▓█ Error █▓▒░',7,13,10
DB 'Cannot create the disk file.',13,10
db '$'
WorkedMsg DB 'CMOS successfully saved',13,10
db '$'
EndIf
If Generating eq CMOSRest
BannerMsg DB '░▒▓█ CMOSRest 1.1 █▓▒░',13d,10d
DB 13d,10d
DB 'Restores CMOS from a CMOSSave file on hard disk or floppy.',13,10
DB 'Copyright (c) 1991 Roedy Green Canadian Mind Products',13,10
DB 'May be freely distributed and used for any purpose except military.',13,10
DB 13,10
db '$'
UsageMsg DB '░▒▓█ Error █▓▒░',13,10
DB 'Insert the diskette you used for CMOSSave.',13,10
DB 'then try:',13,10
DB 'CMOSRest A:MyCMOS.Sav',13,10
DB 'or if the file is on hard disk try:',13,10
DB 'CMOSRest C:\MyCMOS.Sav',13,10
DB 'Read CMOS.TXT to find how to use it properly.',13,10
db '$'
FileTroubleMsg DB '░▒▓█ Error █▓▒░',7,13,10
DB 'Cannot find/read the disk file.',13,10
db '$'
WorkedMsg DB 'CMOS successfully restored',13,10
db '$'
EndIf
If Generating eq CMOSChk
BannerMsg DB '░▒▓█ CMOSChk 1.1 █▓▒░',13d,10d
DB 13d,10d
DB 'Ensures CMOS not corrupted or changed.',13,10
DB 'Copyright (c) 1991 Roedy Green Canadian Mind Products',13,10
DB 'May be freely distributed and used for any purpose except military.',13,10
DB 13,10
db '$'
UsageMsg DB '░▒▓█ Error █▓▒░',7,13,10
DB 'Insert the diskette you used for CMOSSave.',13,10
DB 'then try:',13,10
DB 'CMOSChk A:MyCMOS.Sav',13,10
DB 'or if you have the file on hard disk try:',13,10
DB 'CMOSChk C:\MyCMOS.Sav',13,10
DB 'Read CMOS.TXT to find how to use it properly.',13,10
db '$'
FileTroubleMsg DB '░▒▓█ Error █▓▒░',7,13,10
DB 'Cannot find/read the disk file.',13,10
db '$'
MatchTroubleMsg DB '░▒▓█ Error █▓▒░',7,13,10
DB 'CMOS has been corrupted!',13,10
db '$'
WorkedMsg DB 'CMOS is OK, i.e. unchanged since the last CMOSSave.',13,10
db '$'
EndIf
FilenamePtr DW 0
; pointer to filename in command line
CMOSSize DB 0
; size of cmos in bytes
CMOSBuff db 0 ; dynamic buffer will grow to 128
; it hangs out past the end of the program
data ends
com group code,data ; force data segment to go at the end
ASSUME CS:com,DS:com,ES:com,SS:com
; seg regs cover everything
ORG 100H ; in Code segment
;==========================
Main proc far
; M A I N L I N E R O U T I N E
Start:
lea dx,BannerMsg ; display the banner
Call Say
Call Parse ; get filename from command line
If Generating eq CMOSSave
call GetCMOS ; fetch CMOS to buffer
call WriteCMOS ; write CMOS contents to file
EndIf
If Generating eq CMOSRest
call ReadCMOS ; read CMOS contents from file
call CalcCMOSSize ; it is 64 or 128 bytes long?
call PutCMOS ; store buffer to CMOS
EndIf
If Generating eq CMOSChk
call ReadCMOS ; read CMOS contents from file
call CalcCMOSSize ; it is 64 or 128 bytes long?
call CompareCMOS ; compare CMOS with buffer
EndIf
lea dx,WorkedMsg ; crow about success
Call Say
Done:
mov ax,4c00h
int 21h ;normal termination
Main EndP
;===============================================================
Trouble proc near
FileTrouble:
Lea dx,FileTroubleMsg ; display file trouble
Call Say
Jmp Abort
abort:
; error exit
mov ax, 4c04h ; ERRORLEVEL = 4
int 21h ; DIE
Trouble endp
;===============================================================
MLeading PROC Near
; Remove leading blanks
; on entry BX is addr of string, CX its length
; trims off any leading blanks, leaving result in BX CX
; length may also be 0 or 1, but not -ve
; If the entire string is blank the result is the null string
mov di,bx
mov al,20H ; AL = blank -- the search char
jcxz mleading2 ; jump if null string
repe scasb ; scan ES:DI forwards till hit non blank
; DI points just after it (wrap ok)
; cx IS ONE TOO SMALL, OR 0 IF NONE FOUND
je mleading1 ; jump if entire string was blank
inc cx ; CX is length of remainder of string
mleading1:
dec di ; DI points to non-blank
mleading2:
mov bx,di ; put address back
ret
MLeading ENDP
;========================================
MTrailing PROC Near
; Remove trailing blanks.
; on entry BX is addr of string, CX its length
; trims off any trailing blanks, leaving result in BX CX
; length may also be 0 or 1, but not -ve
; If the entire string is blank the result is the null string
mov di,bx
add di,cx ; calc addr last char in string
dec di
mov al,20H ; AL = blank -- the search char
jcxz mtrailing1 ; jump if null string
std
repe scasb ; scan ES:DI backwards till hit non blank
; DI points just ahead of it (wrap ok)
; CX is one too small, or 0 if none found
cld
je mtrailing1 ; jump if whole string was blank
inc cx
mtrailing1:
ret
MTrailing ENDP
;========================================
Parse PROC NEAR
; Parse the command line to remove lead/trail blanks from
; the single drive parameter and terminate it by 2 nulls.
; sample inputs
; CMOSRest A:\MyCMOS.SAV
; CMOSRest B:\MySub\MyCMOS.SAV
;
; When Done DS:BX points to start of string.
; String will be terminated by 2 nulls
; CX counts bytes in string exclusive of nulls
; counted string at HEX 80 PSP
; contains command line.
; Preceeded by unwanted spaces.
; possibly followed by unwanted spaces.
; currently missing a trailing null.
xor ch,ch
mov cl,ds:80H
mov bx,81H
call Mleading ; get rid of leading blanks
call MTrailing ; get rid of trailing blanks
mov di,bx ; calc addr of byte just past end
add di,cx
mov word ptr [di],0 ; plop in pair of nulls after string
mov FileNamePtr,bx ; remember where filename was
jcxz SyntaxTrouble ; missing parm.
ret
SyntaxTrouble:
lea dx,UsageMsg ; display usage message
Call Say
Jmp Abort
Parse ENDP
;======================================
Say Proc
; on entry DX points to a string to display
MOV AH,9
Int 21h
ret
Say EndP
;======================================
If Generating eq CMOSSave
GetCMOS Proc Near
; Get 128 byte contents of CMOS into a buffer.
mov cx,128 ; count of times through loop
lea bx,CMOSBuff ; where to put the contents
sub al,al ; start offset in CMOS
GetLoop:
Call PeekCmos ; al=offset ah=contents
mov byte ptr[bx],ah
inc al
inc bx
loop GetLoop
ret
GetCMOS EndP
EndIf
;===============================================================
If Generating eq CMOSRest
PutCMOS Proc Near
; Put 128-byte contents of buffer into CMOS.
; do not touch the volatile bytes
mov cx,128 ; count of times through loop
lea bx,CMOSBuff ; where to put the contents
sub al,al ; start offset in CMOS
PutLoop:
call Volatile ; test if this is a volatile byte
; test offset in al
jc LeaveItAlone
mov ah,byte ptr[bx]
Call PokeCMOS ; al=offset ah=contents
LeaveItAlone:
inc bx
inc al
loop PutLoop
ret
PutCMOS EndP
EndIf
;===============================================================
If Generating eq CMOSChk
CompareCMOS proc Near
; compares buffer version of CMOS with contents of actual CMOS
; ignores mismatches of volatile bytes.
; Aborts if finds a mismatch
mov cx,128 ; count of times through loop
lea bx,CMOSBuff ; where to find comparison set
sub al,al ; start offset in CMOS
CompLoop:
call Volatile ; test if this is a volatile byte
; test offset in al
jc IgnoreMismatch
Call PeekCMOS ; al=offset ah=contents
cmp ah,byte ptr[bx] ; compare CMOS with buffer
jne MatchTrouble
IgnoreMismatch:
inc bx
inc al
loop CompLoop
ret
MatchTrouble:
lea dx,MatchTroubleMsg ; display CMOS mismatch
call Say
mov ax, 4c01h ; ERRORLEVEL = 1
int 21h ; DIE
CompareCMOS EndP
EndIf
;===============================================================
If Generating ne CMOSSave
Volatile Proc near
; Is cmos offset in AL volatile? If so set carry.
; These bytes will be undisturbed.
; Preserves all registers.
; 00..0F and 32 are volatile, rest are not.
; if cmos is small, all bytes past end are considered volatile
cmp al,CMOSSize ; bytes past end are volatile
jae IsVolatile
cmp al,0fh
jbe IsVolatile ; early bytes are for timing
cmp al,32h ; 32 is date century byte,
je IsVolatile ; not exactly volatile, but ...
IsNotVolatile:
clc ; clear carry
ret
IsVolatile:
stc
ret
Volatile EndP
EndIf
;===============================================================
If Generating ne CMOSSave
CalcCMOSSize Proc near
; Is CMOS 64 or 128 bytes long?
; It is 64 if bytes at 10..2F match those at 50..6F.
; Otherwise it is 128 bytes.
; Preserves all registers.
push si
push di
push cx
lea si,CMOSBuff+10h
lea di,CMOSBuff+50h
mov cx,02fh+1-10h
repe cmpsb
je IsCMOS64
IsCMOS128:
mov CMOSSize,128 ; differ, must be a big CMOS
jmp CalcCMOSSizeDone
IsCMOS64:
mov CMOSSize,64 ; all same, small CMOS
CalcCMOSSizeDone:
pop cx
pop di
pop si
ret
CalcCMOSSize EndP
EndIf
;===============================================================
if Generating ne CMOSRest
PeekCMOS proc near
; Reads one byte from cmos.
; on entry al has offset desired
; on exit ah has the contents of that byte.
; preserves all registers
; See page 5-81 IBM AT Tech ref BIOS listing for how to read CMOS
; We always enable the NMI with bit 7 on.
push bx
push ax
cli ; disable interrupts
or al,80h ; disable NMI
out 70h,al ; output the byte address to CMOS
jmp $+2 ; delay, safer than nop
in al,71h ; read the CMOS byte
jmp $+2 ; delay, safer than nop
mov bl,al
; re-enable the NMI
mov al,0dh ; point to battery status register
out 70h,al ; leave pointing at a safe r/o register
sti ; restore interrupts
pop ax
mov ah,bl
pop bx
ret
PeekCMOS EndP
EndIf
;===============================================================
If Generating eq CMOSRest
PokeCMOS proc near
; Stuffs one byte into cmos.
; on entry al has offset desired, ah has the value to stuff.
; Preserves all registers.
; See page 5-81 IBM AT Tech ref BIOS listing for how to write CMOS
; We always enable the NMI with bit 7 on.
push ax
cli ; disable interrupts
or al,80h ; disable NMI
out 70h,al ; output the byte address to CMOS
jmp $+2 ; delay, safer than nop
mov al,ah ; get contents
out 71h,al ; poke the CMOS byte
jmp $+2 ; delay, safer than nop
; re-enable the NMI
mov al,0dh ; point to battery status register
out 70h,al ; leave pointing at a safe r/o register
sti ; restore interrupts
pop ax
ret
PokeCMOS EndP
EndIf
;===============================================================
If Generating ne CMOSSave
ReadCMOS Proc Near
; Open a file read the CMOS into a buffer
mov dx,FileNamePtr ; DS:DX point to file
xor al,al ; AL=0 is attribute read/only
mov ah,03Dh ; DOS open function
int 21h
jc FileTrouble
mov bx,ax ; save handle
mov cx,128 ; read 128 bytes
lea dx,CMOSBuff ; buffer address
mov ah,3fH ; DOS read
int 21h
jc FileTrouble
cmp ax,128
jne FileTrouble
mov ah,3eh ; DOS close
int 21h
jc FileTrouble
ret
ReadCMOS EndP
EndIf
;===============================================================
if Generating eq CMOSSave
WriteCMOS Proc Near
; Create a file write CMOS to it
mov dx,FileNamePtr ; DS:DX point to file
xor cx,cx ; CX=0 is attribute
mov ah,03ch ; DOS create function
int 21h
jc FileTrouble
mov bx,ax ; SAVE HANDLE
MOV CX,128 ; write 128 bytes
lea dx,CMOSBuff ; buffer address
mov ah,40h ; DOS write
int 21h
jc FileTrouble
cmp ax,128
jne FileTrouble
mov ah,3eh ; DOS close
int 21h
jc FileTrouble
ret
WriteCMOS EndP
EndIf
;===============================================================
CODE ends ; end of code segment
end Start